﻿using System;
using System.Runtime.InteropServices;

namespace CommonLibrary.Helpers
{
    class GetStructureReader {
        [DllImport("user32.dll", EntryPoint = "GetWindowThreadProcessId")]
        public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);

        //[DllImport("kernel32.dll", EntryPoint = "ReadProcessMemory")]
        //public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, UInt32 nSize, ref UInt32 lpNumberOfBytesRead);

        [DllImport("kernel32.dll")]
        public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] buffer, UInt32 size, out UInt32 lpNumberOfBytesRead); 
 

        public T GetStructure<T>(IntPtr processHandle, IntPtr address, int structSize = 0) {
            if (structSize == 0)
                structSize = Marshal.SizeOf(typeof(T));
            byte[] bytes = new byte[structSize];
            uint numRead = 0;            
            if (!ReadProcessMemory(processHandle, address, bytes, (uint) bytes.Length, out numRead))
                throw new Exception("ReadProcessMemory failed");
            if (numRead != bytes.Length)
                throw new Exception("Number of bytes read does not match structure size");
            GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
            T structure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
            handle.Free();
            return structure;
        }  
    }
}


